package org.wutopia.labcloud.domain.product.service.impl.dubbo;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.seata.rm.tcc.api.BusinessActionContext;
import org.springframework.stereotype.Service;
import org.wutopia.labcloud.domain.product.constant.TccFenceType;
import org.wutopia.labcloud.domain.product.dao.ProductStockpileDao;
import org.wutopia.labcloud.domain.product.dao.MyTccFenceLogDao;
import org.wutopia.labcloud.domain.product.dao.entity.mysql.ProductStockpile;
import org.wutopia.labcloud.domain.product.dao.entity.mysql.MyTccFenceLog;
import org.wutopia.labcloud.service.api.service.seata.TccProductService;

@DubboService
@AllArgsConstructor
@Service
@Slf4j
public class TccProductServiceImpl implements TccProductService {

    private ProductStockpileDao productStockpileDao;

    private MyTccFenceLogDao tccFenceLogDao;

    @Override
    public boolean productStockpileFrozen(BusinessActionContext actionContext, Long productId, Integer frozen) throws Exception {
        // 防止悬挂
        QueryWrapper<MyTccFenceLog> q = new QueryWrapper<>();
        q.eq("xid", actionContext.getXid());
        q.eq("branch_id", actionContext.getBranchId());
        MyTccFenceLog tccFenceLog = tccFenceLogDao.selectOne(q);

        if(tccFenceLog != null && TccFenceType.SUSPENDED.equals(tccFenceLog.getStatus())) {
            return true;
        }


        if(productId == null || frozen == null || frozen < 0) {

            throw new Exception("入参错误");
        }

        QueryWrapper<ProductStockpile> q1 = new QueryWrapper<>();
        q1.eq("product_id", productId);
        ProductStockpile productStockpile = productStockpileDao.selectOne(q1);

        Integer amount = productStockpile.getAmount();
        if(amount.compareTo(frozen) < 0) {
            throw new Exception("库存小于冻结库存数量");
        }
        Integer frozenAmount = productStockpile.getFrozen();


        Integer newAmount = amount - frozen;
        Integer newFrozenAmount = frozenAmount + frozen;
        UpdateWrapper<ProductStockpile> wrapper = new UpdateWrapper<>();
        wrapper.eq("product_id", productId)
                .set("amount", newAmount)
                .set("frozen", newFrozenAmount);
        productStockpileDao.update(wrapper);


        MyTccFenceLog tccFence = new MyTccFenceLog();
        tccFence.setXid(actionContext.getXid());
        tccFence.setBranchId(actionContext.getBranchId());
        tccFence.setStatus(TccFenceType.TRY_SUCCESS);
        tccFence.setActionName("productStockpileFrozen");
        tccFenceLogDao.insert(tccFence);

        return true;
    }

    @Override
    public boolean productStockpileAccomplish(BusinessActionContext actionContext) throws Exception {

        // 幂等
        QueryWrapper<MyTccFenceLog> q = new QueryWrapper<>();
        q.eq("xid", actionContext.getXid());
        q.eq("branch_id", actionContext.getBranchId());
        MyTccFenceLog tccFenceLog = tccFenceLogDao.selectOne(q);

        if(tccFenceLog == null || TccFenceType.COMMITTED.equals(tccFenceLog.getStatus())) {
            return true;
        }

//        if(productId == null || frozen == null || frozen < 0) {
//            throw new Exception("入参错误");
//        }
//
//        QueryWrapper<ProductStockpile> q = new QueryWrapper<>();
//        q.eq("product_id", productId);
//        ProductStockpile productStockpile = productStockpileDao.selectOne(q);
//
//        Integer frozenAmount = productStockpile.getFrozen();
//        if(frozenAmount.compareTo(frozen) < 0) {
//            throw new Exception("冻结库存小于需要释放的库存数量");
//        }
//
//        Integer newFrozenAmount = frozenAmount - frozen;
//
//        UpdateWrapper<ProductStockpile> wrapper = new UpdateWrapper<>();
//        wrapper.eq("product_id", productId)
//                .set("frozen", newFrozenAmount);
//        productStockpileDao.update(wrapper);

        UpdateWrapper<MyTccFenceLog> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("xid", actionContext.getXid());
        updateWrapper.eq("branch_id", actionContext.getBranchId());
        updateWrapper.set("status", TccFenceType.COMMITTED);
        updateWrapper.set("action_name", "productStockpileAccomplish");

        tccFenceLogDao.update(updateWrapper);


        return true;
    }

    @Override
    public boolean productStockpileFrozenThawed(BusinessActionContext actionContext) throws Exception {

        // 防止空回滚
        QueryWrapper<MyTccFenceLog> q = new QueryWrapper<>();
        q.eq("xid", actionContext.getXid());
        q.eq("branch_id", actionContext.getBranchId());
        MyTccFenceLog tccFenceLog = tccFenceLogDao.selectOne(q);
        // 如果 无记录 不回滚, 记录悬挂状态
        if(tccFenceLog == null) {
            MyTccFenceLog log = new MyTccFenceLog();
            log.setXid(actionContext.getXid());
            log.setBranchId(actionContext.getBranchId());
            log.setStatus(TccFenceType.SUSPENDED);
            log.setActionName("productStockpileFrozenThawed");
            tccFenceLogDao.insert(log);
            return true;
        }

        // 幂等
        if(TccFenceType.CANCELED.equals(tccFenceLog.getStatus()) || TccFenceType.SUSPENDED.equals(tccFenceLog.getStatus())) {
            return true;
        }

        Long productId = actionContext.getActionContext("productId", Long.class);
        Integer frozen = actionContext.getActionContext("frozen", Integer.class);


        if(productId == null || frozen == null || frozen < 0) {
            throw new Exception("入参错误");
        }

        QueryWrapper<ProductStockpile> q1 = new QueryWrapper<>();
        q1.eq("product_id", productId);
        ProductStockpile productStockpile = productStockpileDao.selectOne(q1);

        Integer amount = productStockpile.getAmount();

        Integer frozenAmount = productStockpile.getFrozen();
        if(frozenAmount.compareTo(frozen) < 0) {
            throw new Exception("冻结库存小于需要释放的库存数量");
        }

        Integer newAmount = amount + frozen;
        Integer newFrozenAmount = frozenAmount - frozen;

        UpdateWrapper<ProductStockpile> wrapper = new UpdateWrapper<>();
        wrapper.eq("product_id", productId)
                .set("amount", newAmount)
                .set("frozen", newFrozenAmount);
        productStockpileDao.update(wrapper);

        UpdateWrapper<MyTccFenceLog> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("xid", actionContext.getXid());
        updateWrapper.eq("branch_id", actionContext.getBranchId());
        updateWrapper.set("status", TccFenceType.CANCELED);
        updateWrapper.set("action_name", "productStockpileFrozenThawed");

        tccFenceLogDao.update(updateWrapper);
        return true;
    }



    @Override
    public boolean stockpileFrozenReturn(BusinessActionContext actionContext, Long productId, Integer frozen)  {

        QueryWrapper<ProductStockpile> q1 = new QueryWrapper<>();
        q1.eq("product_id", productId);
        ProductStockpile productStockpile = productStockpileDao.selectOne(q1);

        if (productStockpile.getFrozen() < frozen) {
            log.error("错误：冻结库存小于需要海原的库存");
            return false;
        }

        Integer newFrozne = productStockpile.getFrozen() - frozen;

        Integer newAmount = productStockpile.getAmount() + frozen;
        UpdateWrapper<ProductStockpile> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("product_id", productId);
        updateWrapper.set("frozen", newFrozne);
        updateWrapper.set("amount", newAmount);
        productStockpileDao.update(updateWrapper);

        return true;
    }

    @Override
    public boolean stockpileReturnAccomplish(BusinessActionContext actionContext) {


        return true;
    }

    @Override
    public boolean stockpileFrozenCancel(BusinessActionContext actionContext)  {

        Long productId = actionContext.getActionContext("productId", Long.class);
        Integer frozen = actionContext.getActionContext("frozen", Integer.class);

        if(frozen == null || productId ==null ) {
            log.error("订单超时cancel错误：无法获取productId和frozen");
            return false;
        }
        QueryWrapper<ProductStockpile> q1 = new QueryWrapper<>();
        q1.eq("product_id", productId);
        ProductStockpile productStockpile = productStockpileDao.selectOne(q1);

        if (productStockpile.getAmount() < frozen) {
            log.error("订单超时cancel错误：当前库存小于需要返还冻结库存");
            return false;
        }

        Integer newFrozne = productStockpile.getFrozen() + frozen;

        Integer newAmount = productStockpile.getAmount() - frozen;
        UpdateWrapper<ProductStockpile> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("product_id", productId);
        updateWrapper.set("frozen", newFrozne);
        updateWrapper.set("amount", newAmount);
        productStockpileDao.update(updateWrapper);

        return true;
    }

    @Override
    public boolean stockpileFrozenRelease(BusinessActionContext actionContext, Long productId, Integer frozen) throws Exception {

        if(productId == null || frozen == null || frozen < 0) {
            throw new Exception("入参错误");
        }

        QueryWrapper<ProductStockpile> q = new QueryWrapper<>();
        q.eq("product_id", productId);
        ProductStockpile productStockpile = productStockpileDao.selectOne(q);

        Integer frozenAmount = productStockpile.getFrozen();
        if(frozenAmount.compareTo(frozen) < 0) {
            throw new Exception("冻结库存小于需要释放的库存数量");
        }

        Integer newFrozenAmount = frozenAmount - frozen;

        UpdateWrapper<ProductStockpile> wrapper = new UpdateWrapper<>();
        wrapper.eq("product_id", productId)
                .set("frozen", newFrozenAmount);
        productStockpileDao.update(wrapper);


        return true;
    }

    @Override
    public boolean stockpileReleaseAccomplish(BusinessActionContext actionContext) {
        return true;
    }

    @Override
    public boolean stockpileReleaseCancel(BusinessActionContext actionContext) throws Exception {


        Long productId = actionContext.getActionContext("productId", Long.class);
        Integer frozen = actionContext.getActionContext("frozen", Integer.class);

        if(productId == null || frozen == null || frozen < 0) {
            throw new Exception("入参错误");
        }

        QueryWrapper<ProductStockpile> q = new QueryWrapper<>();
        q.eq("product_id", productId);
        ProductStockpile productStockpile = productStockpileDao.selectOne(q);

        Integer frozenAmount = productStockpile.getFrozen();
//        if(frozenAmount.compareTo(frozen) < 0) {
//            throw new Exception("冻结库存小于需要释放的库存数量");
//        }

        Integer newFrozenAmount = frozenAmount + frozen;

        UpdateWrapper<ProductStockpile> wrapper = new UpdateWrapper<>();
        wrapper.eq("product_id", productId)
                .set("frozen", newFrozenAmount);
        productStockpileDao.update(wrapper);
        return true;
    }
}
